package com.zzl.admin.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import org.junit.jupiter.api.Test;

import java.util.Date;

/**
 * description: 测试JWT的使用
 * @author 朱正磊
 * @date 2022-08-12 15:43:19
 */
public class JwtTest2 {

    /**
     * 利用JWT生成token
     */
    @Test
    void test1() {
        // 生成token，有效期为1分钟
        String token = this.sign("lisi", 1, "123456", 3 * 60 * 1000L);
        // token = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVHlwZSI6MSwiZXhwIjoxNjYwMjc2MDk0LCJ1c2VybmFtZSI6Imxpc2kifQ.0xeeji1rT5cpKkoiQo-7onwqPgApNE8u9W3fkCQyP38
        System.out.println("token = " + token);
    }

    /**
     * 解析token得到用户名，即使token已经过期也能解析成功
     */
    @Test
    void test2() {
        String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVHlwZSI6MSwiZXhwIjoxNjYwMjc2MDk0LCJ1c2VybmFtZSI6Imxpc2kifQ.0xeeji1rT5cpKkoiQo-7onwqPgApNE8u9W3fkCQyP38";
        String username = this.getUsername(token);
        // username = lisi
        System.out.println("username = " + username);
    }

    /**
     * 解析token得到用户类型，即使token已经过期也能解析成功
     */
    @Test
    void test3() {
        String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVHlwZSI6MSwiZXhwIjoxNjYwMjc2MDk0LCJ1c2VybmFtZSI6Imxpc2kifQ.0xeeji1rT5cpKkoiQo-7onwqPgApNE8u9W3fkCQyP38";
        Integer userType = this.getUserType(token);
        // userType = 1
        System.out.println("userType = " + userType);
    }

    /**
     * 只使用密钥校验token，可以校验没有问题
     */
    @Test
    void test4() {
        String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVHlwZSI6MSwiZXhwIjoxNjYwMjc2MDk0LCJ1c2VybmFtZSI6Imxpc2kifQ.0xeeji1rT5cpKkoiQo-7onwqPgApNE8u9W3fkCQyP38";
        String secret = "123456";
        boolean flag = this.verify(token, secret);
        // flag = false
        System.out.println("flag = " + flag);
    }

    /**
     * 使用密钥和部分载荷校验token，可以校验也没有问题
     */
    @Test
    void test5() {
        String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVHlwZSI6MSwiZXhwIjoxNjYwMjc2MDk0LCJ1c2VybmFtZSI6Imxpc2kifQ.0xeeji1rT5cpKkoiQo-7onwqPgApNE8u9W3fkCQyP38";
        String username = "lisi";
        String secret = "123456";
        boolean flag = this.verify(token, username, secret);
        // flag = false
        System.out.println("flag = " + flag);
    }

    /**
     * description: 利用JWT生成token
     * @author 朱正磊
     * @date 2022-08-12 11:07:53
     * @param username 用户名
     * @param userType 用户类型
     * @param secret 密钥
     * @param expireTime 过期时间
     * @return 返回token
     */
    private String sign(String username, Integer userType, String secret, Long expireTime) {
        Date date = new Date(System.currentTimeMillis() + expireTime);
        Algorithm algorithm = Algorithm.HMAC256(secret);
        return JWT.create()
                .withClaim("username", username)
                .withClaim("userType", userType)
                .withExpiresAt(date)
                .sign(algorithm);
    }

    /**
     * description: 校验token
     * @author 朱正磊
     * @date 2022-08-12 11:12:31
     * @param token token
     * @param secret 密钥
     * @return 校验成功返回true，否则返回false
     */
    private boolean verify(String token, String secret) {
        try {
            JWT.require(Algorithm.HMAC256(secret)).build().verify(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * description: 校验token
     * @author 朱正磊
     * @date 2022-08-12 11:11:35
     * @param token token
     * @param username 用户名
     * @param secret 密钥
     * @return 校验成功返回true，否则返回false
     */
    private boolean verify(String token, String username, String secret) {
        try {
            JWT.require(Algorithm.HMAC256(secret)).withClaim("username", username).build().verify(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * description: 解析token得到用户名
     * @author 朱正磊
     * @date 2022-08-12 11:15:42
     * @param token token
     * @return 返回用户名
     */
    private String getUsername(String token) {
        try {
            return JWT.decode(token).getClaim("username").asString();
        } catch (JWTDecodeException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * description: 解析token得到用户类型
     * @author 朱正磊
     * @date 2022-08-12 11:15:48
     * @param token token
     * @return 返回用户类型
     */
    private Integer getUserType(String token) {
        try {
            return JWT.decode(token).getClaim("userType").asInt();
        } catch (JWTDecodeException e) {
            e.printStackTrace();
            return null;
        }
    }

}
